use std::{
    fs,
    io::{Read, Write as _},
    path::{Path, PathBuf},
  };
  
  use e_utils::{cmd::Cmd, fs::AutoPath as _, parse::MyParseFormat};
  use regex::Regex;
  
  use crate::share::SYSTEM_WIN32;
  
  /// 激活存储本地类型
  #[derive(Debug, Clone)]
  pub enum ActiveLocalType {
    Temp(String),
  }
  /// Office激活版本
  #[derive(PartialEq, Clone, Debug)]
  pub enum OfficeVersion {
    V2003,
    V2006,
    V2010,
    V2013,
    V2016,
    V2019,
    V365,
    None,
  }
  impl OfficeVersion {
    ///
    pub fn find_version(version: OfficeVersion, l: &Vec<(Self, PathBuf)>) -> (Self, PathBuf) {
      for x in l {
        if x.0 == version {
          return x.clone();
        }
      }
      (Self::None, PathBuf::new())
    }
    /// 获取凭证路径
    pub fn license_path(&self) -> Option<PathBuf> {
      Some(
        Path::new(match self {
          OfficeVersion::V2003 => "C:\\Program Files\\Microsoft Office\\root\\Licenses3",
          OfficeVersion::V2006 => "C:\\Program Files\\Microsoft Office\\root\\Licenses6",
          OfficeVersion::V2010 => "C:\\Program Files\\Microsoft Office\\root\\Licenses10",
          OfficeVersion::V2013 => "C:\\Program Files\\Microsoft Office\\root\\Licenses13",
          OfficeVersion::V2016 => "C:\\Program Files\\Microsoft Office\\root\\Licenses16",
          OfficeVersion::V2019 => "C:\\Program Files\\Microsoft Office\\root\\Licenses19",
          OfficeVersion::V365 => "C:\\Program Files\\Microsoft Office\\root\\Licenses365",
          OfficeVersion::None => return None,
        })
        .to_path_buf(),
      )
    }
  }
  /// # 清除激活码持久化
  /// # Example sh
  /// ```sh
  /// e-app.exe --api active --task cleanCache -- fname.txt
  /// ```
  pub fn clean_cache(save_type: ActiveLocalType) -> e_utils::AnyResult<String> {
    match save_type {
      ActiveLocalType::Temp(fname) => {
        let tmp = "%TEMP%".parse_env()?;
        let path = Path::new(&tmp).join(&format!("os-key-{fname}"));
        if (path.exists() && path.auto_remove_file().is_ok()) || !path.exists() {
          Ok(format!("清除本地激活码"))
        } else {
          Err(format!("Error: Clean Cache;{}", path.display()).into())
        }
      }
    }
  }
  /// # 查询激活码持久化
  /// # Example sh
  /// ```sh
  /// e-app.exe --api active --task queryCache -- fname.txt
  /// ```
  pub fn query_cache(save_type: ActiveLocalType) -> e_utils::AnyResult<String> {
    match save_type {
      ActiveLocalType::Temp(fname) => {
        let tmp = "%TEMP%".parse_env()?;
        let path = Path::new(&tmp).join(&format!("os-key-{fname}"));
        if path.exists() {
          let mut f = fs::OpenOptions::new().read(true).open(&path)?;
          let mut sbuf = String::new();
          if f.read_to_string(&mut sbuf).is_ok() && sbuf.len() > 3 {
            return Ok(sbuf);
          }
        }
        Err(format!("Error: Query Cache;{}", path.display()).into())
      }
    }
  }
  
  /// # 检查OS是否激活
  /// # Example sh
  /// ```sh
  /// e-app.exe --api active --task check
  /// ```
  pub fn check_os_active() -> e_utils::AnyResult<String> {
    // 执行 slmgr.vbs 命令
    let output = Cmd::new("cscript")
      .args(["/nologo", "slmgr.vbs", "-xpr"])
      .cwd(SYSTEM_WIN32)
      .output()?;
    let output = output.stdout;
    // 在输出中查找激活状态
    if output.contains("激活") || output.contains("activated") {
      return Ok(output);
    }
    Err("Error: Check OS Not Active".into())
  }
  
  /// 激活系统
  /// # Example sh
  /// ```sh
  /// e-app.exe --api active --task active -- YVWGF-BXNMC-HTQYQ-CPQ99-66QFC fname.txt
  /// ```
  pub fn active_os(product_key: &str, save_type: ActiveLocalType) -> e_utils::AnyResult<String> {
    if let Ok(re) = Regex::new(r"^[0-9A-Z]{5}-(?:[0-9A-Z]{5}-){3}[0-9A-Z]{5}$") {
      // Define the optimized regular expression pattern for a Microsoft product key
      if !re.is_match(product_key) {
        return Err(format!("Error: Active Code of Rule,Please check;{product_key}").into());
      }
    }
    let cmd = Cmd::new("cscript")
      .args(["/nologo", "slmgr.vbs"])
      .cwd(SYSTEM_WIN32);
    // Execute the slmgr.vbs script with the /ipk argument to install the product key
    let output = cmd
      .clone()
      .args(["/ipk", product_key])
      .output()
      .map_err(|e| format!("Error: Install Product Active Code: {product_key};{e}"))?;
    // Activate Windows using the installed product key
    let o2 = cmd
      .arg("/ato")
      .output()
      .map_err(|e| format!("Error: Active Code: {product_key};{e}"))?;
    // 在输出中查找激活状态
    if o2.stdout.contains("激活") || o2.stdout.contains("activated") {
      match save_type {
        ActiveLocalType::Temp(fname) => {
          if let Ok(tmp) = "%TEMP%".parse_env() {
            let path = Path::new(&tmp).join(&format!("os-key-{fname}"));
            if let Ok(mut f) = fs::OpenOptions::new()
              .read(true)
              .write(true)
              .create(true)
              .open(&path)
            {
              let _ = f.write(product_key.as_bytes());
            }
          }
        }
      }
      return Ok(format!("{};{}", output.stdout, o2.stdout));
    }
    Err(format!("Error: Active Code: {product_key}; {}", o2.stdout).into())
  }
  
  /// # 取消注册
  /// # Example sh
  /// ```sh
  /// e-app.exe --api active --task deactive
  /// ```
  pub fn deactivate_os() -> e_utils::AnyResult<String> {
    let cmd = Cmd::new("cscript")
      .args(["/nologo", "slmgr.vbs"])
      .cwd(SYSTEM_WIN32);
    let out = cmd
      .output()
      .map_err(|e| format!("Error: Uninstall the product key;{e}"))?;
    let x2 = cmd
      .clone()
      .arg("/cpky")
      .output()
      .map_err(|e| format!("Error: remove the product key from the registry;{e}"))?;
    let x3 = cmd
      .arg("/rearm")
      .output()
      .map_err(|e| format!("Error: remove the product key from the registry;{e}"))?;
    Ok(format!("{};{};{}", out.stdout, x2.stdout, x3.stdout))
  }
  
  /// # 注册KMS
  /// # Example sh
  /// ```sh
  /// e-app.exe --api active --task rkms -- kms.03k.org
  /// ```
  pub fn register_kms(server: &str) -> e_utils::AnyResult<String> {
    Ok(
      Cmd::new("cscript")
        .args(["/nologo", "slmgr.vbs", "/skms"])
        .cwd(SYSTEM_WIN32)
        .output()
        .map_err(|e| format!("Error: registry KMS {server};{e}"))?
        .stdout,
    )
  }
  
  /// # 清除注册KMS
  /// # Example sh
  /// ```sh
  /// e-app.exe --api active --task ckms
  /// ```
  pub fn clear_kms() -> e_utils::AnyResult<String> {
    Ok(
      Cmd::new("cscript")
        .args(["/nologo", "slmgr.vbs", "/ckms"])
        .cwd(SYSTEM_WIN32)
        .output()
        .map_err(|e| format!("Error: Clear KMS;{e}"))?
        .stdout,
    )
  }
  
  /// # 检查OFFICE
  /// # Example sh
  /// ```sh
  /// e-app.exe --api office --task check -- V2016
  /// ```
  pub fn check_office(v: OfficeVersion) -> e_utils::AnyResult<String> {
    let olist = check_office_dir().unwrap_or_default();
    let office = OfficeVersion::find_version(v, &olist);
    match office.0 {
      OfficeVersion::None => {
        Err(format!("Error: Check Office Not Found {}", office.1.display()).into())
      }
      _ => {
        let exe = "ospp.vbs";
        let exe_path = office.1.join(exe);
        if exe_path.exists() {
          Ok(
            Cmd::new("cscript")
              .args(["/nologo", exe, "/dstatus"])
              .cwd(office.1)
              .output()
              .map_err(|e| format!("Error: Office check;{e}"))?
              .stdout,
          )
        } else {
          Err(format!("Error: Check Office Not Found {}", exe_path.display()).into())
        }
      }
    }
  }
  /// # 注册OFFICE KMS
  /// # Example sh
  /// ```sh
  /// e-app.exe --api office --task rkms -- V2016 kms.03k.org
  /// ```
  pub fn register_office_kms(v: OfficeVersion, server: &str) -> e_utils::AnyResult<String> {
    let olist = check_office_dir().unwrap_or_default();
    let office = OfficeVersion::find_version(v, &olist);
    match office.0 {
      OfficeVersion::None => Err(format!("Error: Check Office Not Found").into()),
      _ => {
        let exe = "ospp.vbs";
        let exe_path = office.1.join(exe);
        if exe_path.exists() {
          Ok(
            Cmd::new("cscript")
              .args(["/nologo", exe, &format!("/sethst:{server}")])
              .cwd(office.1)
              .output()
              .map_err(|e| format!("Error: Office set KMS: {server};{e}"))?
              .stdout,
          )
        } else {
          Err(format!("Error: Check Office Not Found {}", exe_path.display()).into())
        }
      }
    }
  }
  /// # 激活OFFICE
  /// # Example sh
  /// ```sh
  /// e-app.exe --api office --task active -- V2016 NMMKJ-6RK4F-KMJVX-8D9MJ-6MWKP
  /// ```
  pub fn active_office(v: OfficeVersion) -> e_utils::AnyResult<String> {
    let olist = check_office_dir().unwrap_or_default();
    let office = OfficeVersion::find_version(v, &olist);
    match office.0 {
      OfficeVersion::None => Err(format!("Error: Check Office Not Found").into()),
      _ => {
        let exe = "ospp.vbs";
        let exe_path = office.1.join(exe);
        if exe_path.exists() {
          let x2 = Cmd::new("cscript")
            .args(["/nologo", exe, &format!("/act")])
            .cwd(office.1)
            .output()
            .map_err(|e| format!("Error: Active Office;{e}"))?;
          if Regex::new("(successful|成功)")?.is_match(&x2.stdout) {
            Ok(x2.stdout)
          } else {
            Err(format!("Error: Active Office;{}", x2.stdout).into())
          }
        } else {
          Err(format!("Error: Check Office Not Found {}", exe_path.display()).into())
        }
      }
    }
  }
  /// 检查OFFICE路径
  fn check_office_dir() -> Option<Vec<(OfficeVersion, PathBuf)>> {
    let p = Path::new("C:\\Program Files\\Microsoft Office");
    let mut l = vec![];
    if p.exists() {
      for x in p.read_dir().ok()? {
        if let Ok(dir) = x {
          let s = &*dir.file_name().to_string_lossy().to_string();
          let x = match s {
            "Office2003" => OfficeVersion::V2003,
            "Office2006" => OfficeVersion::V2006,
            "Office2010" => OfficeVersion::V2010,
            "Office2013" => OfficeVersion::V2013,
            "Office2016" => OfficeVersion::V2016,
            "Office2019" => OfficeVersion::V2019,
            "Office365" => OfficeVersion::V365,
            _ => OfficeVersion::None,
          };
          if x != OfficeVersion::None {
            l.push((x, dir.path()));
          }
        }
      }
    }
    Some(l)
  }
  